﻿/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
**/

package com.chasekernan.hxnova.core.components;

import com.chasekernan.hxnova.core.minerals.MineralSet;
import com.chasekernan.hxnova.core.stars.Concentrations;
import haxe.xml.Check;

/**
    Stores a defense type as a coverage percent (1.0 = 100%).
    The coverage percent is usually small (like 1%) and is the approximate
    coverage for each individual defense (but additional defensese decrease in
    effectiveness).
**/
class Defense extends Component {
    
    /**
        Having 100% defenses on a world would result in the effectiveness of 
        the defending ground troops being multiplied by this + 1.
    **/
    public static var GROUND_DEFENSE_MULTIPLIER : Int = 2;
    
    public static var COST : { resources : Int, minerals : MineralSet } = 
            setupCost();
            
    
    private static function setupCost() {
        var minerals = new MineralSet();
        for (minType in Concentrations.MINERAL_TYPES) {
            minerals.setValue(minType, 15);
        }
        
        return { resources : 15, minerals : minerals };
    }
    
    public static var MAX_COVERAGE : Float = 0.9999;
    
    public var coverage(default, setCoverage) : Float;
    
    private function setCoverage(c : Float) : Float {
        if (c < 0) throw "Coverage cannot be less than 0.";
        if (c > MAX_COVERAGE) {
            throw "Coverage cannot be greater than " + MAX_COVERAGE;
        }
        coverage = c;
        
        return coverage;
    }
    
    public function new(name : String, ?coverage : Float) {
        super(name);
        this.coverage = if (coverage == null) 0.0001 else coverage;
    }
    
    public static function writeToXml(d : Defense) : Xml {
        return Component.writeToXml(d);
    }
    
    public static function readFromXml(xml : Xml) : Defense {
        try {
            var d = new Defense("");
            //Check.checkNode(xml, d.getRules());
            d.generateFromComponentXml(xml, d);
            
            return d;
        } catch (e : Dynamic) {
            throw 'Bad xml file for defense: ' + e;
        }
    }
    
    /**
        Returns the percent of population covered by the defenses against 
        (normal) bombing. Percentage is normalized so that 1.0 = 100%.
    **/
    public function getPopCoverage(numDefenses : Int) : Float {
        return 1.0 - Math.pow((1.0 - coverage), numDefenses);
    }
    
    /**
        Returns the percent of population covered by the defenses against 
        smart bombing. Percentage is normalized so that 1.0 = 100%.
    **/
    public function getPopCoverageUnderSmartBomb(numDefenses : Int) : Float {
        return 1.0 - Math.pow((1.0 - coverage * 0.5), numDefenses);
    }
    
    /**
        Returns the percent of the buildings covered by the defenses against 
        bombings. Percentage is normalized so that 1.0 = 100%.
    **/
    public function getBuildingCoverage(numDefenses : Int) : Float {
        return getPopCoverage(numDefenses) * 0.5;
    }
    
    /** 
        Returns the factor the defending troops are multiplied by to simulate 
        the advantage of defenses. For example, 100% defenses would result in
        the defending troops' effectiveness being multiplied by 
        1 + [GROUND_DEFENSE_MULTIPLIER].
    **/
    public function getGroundCombatProtection(numDefenses : Int) : Float {
        return getPopCoverage(numDefenses) * GROUND_DEFENSE_MULTIPLIER;
    }
}